/*
 * Copyright (C) 2001-2004 the xine project
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
 *
 * $Id: stream_info.c,v 1.22 2006/04/08 21:34:50 dsalt Exp $
 *
 * stream_info/metadata display dialog implementation
 */

#include "globals.h"

#include <X11/Xlib.h>
#include <gtk/gtk.h>
#include <gdk/gdk.h>
#include <glib.h>
#include <stdio.h>
#include <math.h>

#include "globals.h"
#include "stream_info.h"
#include "utils.h"

static GtkWidget    *dlg;
static int           is_visible;
static GtkListStore *meta_store;

static void add_meta_entry (const gchar *l, int info)
{
  GtkTreeIter  iter;
  const char *str = xine_get_meta_info (stream, info);
  if (!str)
    return;

  gtk_list_store_append (meta_store, &iter);
  gtk_list_store_set (meta_store, &iter, 0, l, 1,
		      g_utf8_normalize (str, -1, G_NORMALIZE_DEFAULT), -1);
}

static void add_string_entry (const gchar *l, char *info)
{
  GtkTreeIter  iter;
  gtk_list_store_append (meta_store, &iter);
  gtk_list_store_set (meta_store, &iter, 0, l, 1,
		      g_utf8_normalize (info, -1, G_NORMALIZE_DEFAULT), -1);
}

static void update_metadata (void)
{
  char str[128];
  int count, w;

  gtk_list_store_clear (meta_store);

  /* Track/stream/file info */

  add_meta_entry (_("Title:"), XINE_META_INFO_TITLE);
  add_meta_entry (_("Artist:"), XINE_META_INFO_ARTIST);
  add_meta_entry (_("Album:"), XINE_META_INFO_ALBUM); //TEST
  add_meta_entry (_("Genre:"), XINE_META_INFO_GENRE); //TEST
  add_meta_entry (_("Comment:"), XINE_META_INFO_COMMENT);
  add_meta_entry (_("Date:"),    XINE_META_INFO_YEAR);

#ifdef XINE_STREAM_INFO_DVD_TITLE_NUMBER
  count = xine_get_stream_info (stream, XINE_STREAM_INFO_DVD_TITLE_COUNT);
  if (count)
  {
    int num = xine_get_stream_info (stream, XINE_STREAM_INFO_DVD_TITLE_NUMBER);
    snprintf (str, sizeof (str), _("%d of %d"), num, count);
    add_string_entry (_("DVD title:"), str);
  }
  count = xine_get_stream_info (stream, XINE_STREAM_INFO_DVD_CHAPTER_COUNT);
  if (count)
  {
    int num = xine_get_stream_info (stream, XINE_STREAM_INFO_DVD_CHAPTER_NUMBER);
    snprintf (str, sizeof (str), _("%d of %d"), num, count);
    add_string_entry (_("Chapter:"), str);
  }
  count = xine_get_stream_info (stream, XINE_STREAM_INFO_DVD_ANGLE_COUNT);
  if (count)
  {
    int num = xine_get_stream_info (stream, XINE_STREAM_INFO_DVD_ANGLE_NUMBER);
    snprintf (str, sizeof (str), _("%d of %d"), num, count);
    add_string_entry (_("Angle:"), str);
  }
#endif

  /* Audio info */

  add_meta_entry (_("Audio codec:"), XINE_META_INFO_AUDIOCODEC);
  count = xine_get_stream_info (stream, XINE_STREAM_INFO_AUDIO_CHANNELS);
  if (count)
  {
    int bits = xine_get_stream_info (stream, XINE_STREAM_INFO_AUDIO_BITS);
    int rate = xine_get_stream_info (stream, XINE_STREAM_INFO_AUDIO_SAMPLERATE);
    int bps  = xine_get_stream_info (stream, XINE_STREAM_INFO_AUDIO_BITRATE);
    snprintf (str, sizeof (str), _("%d channels, %d bit, %3.1fkHz, %d bps"),
	      count, bits, rate / 1000.0, bps);

    add_string_entry (_("Audio format:"), str);
  }

  /* Video info */

  add_meta_entry (_("Video codec:"), XINE_META_INFO_VIDEOCODEC);

  w = xine_get_stream_info (stream, XINE_STREAM_INFO_VIDEO_WIDTH);
  if (w)
  {
#ifdef XINE_STREAM_INFO_VIDEO_AFD
    int afd = xine_get_stream_info (stream, XINE_STREAM_INFO_VIDEO_AFD);
#endif
    int h     = xine_get_stream_info (stream, XINE_STREAM_INFO_VIDEO_HEIGHT);
    int ratio = xine_get_stream_info (stream, XINE_STREAM_INFO_VIDEO_RATIO);
    int bps   = xine_get_stream_info (stream, XINE_STREAM_INFO_VIDEO_BITRATE);
    const char *r;
    double fps;

    if (xine_get_stream_info (stream, XINE_STREAM_INFO_FRAME_DURATION) != 0.0)
      fps = 90000.0 / xine_get_stream_info (stream, XINE_STREAM_INFO_FRAME_DURATION);
    else
      fps = 0.0;

    r = (ratio == 13333) ? "4:3" : (ratio == 17777) ? "16:9" : NULL;
#ifdef XINE_STREAM_INFO_VIDEO_AFD
    if (r && afd >= 0 && afd < 16)
      snprintf (str, sizeof (str), _("%d×%d, %2.1f fps, %s (AFD %d), %d bps"),
		w, h, fps, r, afd, bps);
    else
#endif
    if (r)
      snprintf (str, sizeof (str), _("%d×%d, %2.1f fps, %s, %d bps"),
		w, h, fps, r, bps);
    else
      snprintf (str, sizeof (str), _("%d×%d, %2.1f fps, %4.2f:1, %d bps"),
		w, h, fps, ratio / 10000.0, bps);

    add_string_entry (_("Video format:"), str);
  }

  add_meta_entry (_("System layer:"), XINE_META_INFO_SYSTEMLAYER);

}

void stream_info_show (void)
{
  if (is_visible)
  {
    is_visible = FALSE;
    gtk_widget_hide (dlg);
  }
  else
  {
    is_visible = TRUE;
    update_metadata ();
    window_show (dlg, NULL);
  }
}

static void response_cb (GtkDialog *dbox, int response, gpointer data)
{
  switch (response)
  {
  case GTK_RESPONSE_YES:
    update_metadata ();
    break;
  default:
    is_visible = FALSE;
    gtk_widget_hide (dlg);
  }
}

static JSBool js_stream_info_show (JSContext *cx, JSObject *obj, uintN argc,
				   jsval *argv, jsval *rval)
{
  /* se_t *se = (se_t *) JS_GetContextPrivate(cx); */
  se_log_fncall_checkinit ("stream_info_show");
  stream_info_show ();
  return JS_TRUE;
}

void stream_info_init (void)
{
  GtkTreeView	       *tree_view;
  GtkWidget	       *scrolled_window;
  GtkCellRenderer      *cell;
  GtkTreeViewColumn    *column;

  /* create dialog */

  dlg = gtk_dialog_new_with_buttons (_("Stream meta-info"), NULL, 0,
				GTK_STOCK_REFRESH, GTK_RESPONSE_YES,
				GTK_STOCK_CLOSE, GTK_RESPONSE_DELETE_EVENT,
				NULL);
  gtk_window_set_default_size (GTK_WINDOW (dlg), 500, 400);
  hide_on_delete (dlg, &is_visible);
  g_signal_connect (G_OBJECT(dlg), "response", G_CALLBACK(response_cb), NULL);

  /* add list to hold meta info */

  meta_store = gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_STRING);

  tree_view = GTK_TREE_VIEW (gtk_tree_view_new_with_model (GTK_TREE_MODEL (meta_store)));
  gtk_tree_view_set_rules_hint (tree_view, TRUE);

  cell = gtk_cell_renderer_text_new ();
  column = gtk_tree_view_column_new_with_attributes (_("Field"), cell,
						     "text", 0, NULL);
  gtk_tree_view_column_set_resizable (column, TRUE);
  gtk_tree_view_append_column (tree_view, column);

  column = gtk_tree_view_column_new_with_attributes (_("Data from stream"),
						     cell, "text", 1, NULL);
  gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_AUTOSIZE);
  gtk_tree_view_append_column (tree_view, column);

  scrolled_window = gtk_scrolled_window_new (NULL, NULL);
  gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window),
				  GTK_POLICY_AUTOMATIC,
				  GTK_POLICY_AUTOMATIC);
  gtk_container_add (GTK_CONTAINER (scrolled_window), GTK_WIDGET (tree_view));

  gtk_box_pack_start (GTK_BOX(GTK_DIALOG (dlg)->vbox), scrolled_window,
		      TRUE, TRUE, 2);

  is_visible = FALSE;

  se_defun (gse, NULL, "stream_info_show", js_stream_info_show, 0, 0,
	    SE_GROUP_DIALOGUE, N_("[bool]"), NULL);
}
